package com.farm.project.service.utils;

import java.io.IOException;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;

import com.farm.core.sql.query.DataQuery;
import com.farm.core.sql.result.DataResult;
import com.farm.lucene.FarmLuceneFace;
import com.farm.lucene.common.IRResult;
import com.farm.lucene.common.IndexTaskDomain;
import com.farm.lucene.common.ScoreDocFilterInter;
import com.farm.lucene.server.DocIndexInter;
import com.farm.lucene.server.DocQueryInter;
import com.farm.project.service.TaskServiceInter;

public class IndexUtils {
	private static Map<String, IndexTaskDomain> domains = new HashMap<>();
	public static final String LuceneIndexFileKey = "plogsindex";
	private final static Logger log = Logger.getLogger(IndexUtils.class);

	private static int indexNum = 0;

	public static void indexTaskFile(TaskFileIndexInfo info) {
		DocIndexInter index = null;
		try {
			index = FarmLuceneFace.inctance()
					.getDocIndex(FarmLuceneFace.inctance().getIndexPathFile(LuceneIndexFileKey));
			index.deleteFhysicsIndex(info.getId());
			index.indexDoc(info.getDocMap());
			if (indexNum > 50) {
				indexNum = 0;
				index.mergeIndex();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (index != null) {
				try {
					indexNum++;
					index.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * 启动一个索引重建任务(知识)
	 * 
	 * @param taskkey             任务关键字
	 * @param fileBaseServiceImpl
	 * @param taskServiceImpl
	 * @return 任务状态
	 * @throws IOException
	 */
	public static IndexTaskDomain startReKnowIndexTaskBy(String taskkey, final DataQuery query,
			final TaskServiceInter taskServiceImpl) throws IOException {
		final IndexTaskDomain domain = new IndexTaskDomain(0, 0, 0, "", taskkey);
		domains.put(taskkey, domain);
		Thread t = new Thread(new Runnable() {
			public void run() {
				try {
					DataResult result = null;
					DataQuery query1 = query;
					query1.setCurrentPage(1);
					// 查询分页的当前页面
					int i = 1;
					// 当前任务已处理数量的计数器
					int n = 0;
					while (true) {
						// 本轮开始时已处理过的数量
						domain.setCompletedNum(n);
						List<TaskFileIndexInfo> docs = new ArrayList<>();
						try {
							// 任务状态 0初始化，
							domain.setState(0);
							query1.setPagesize(1000);
							query1.setCurrentPage(i++);
							result = query1.search();
							domain.setMaxNum(result.getTotalSize());
							if (result.getResultList().size() <= 0) {
								break;
							}
							for (Map<String, Object> node : result.getResultList()) {
								n++;
								domain.setProcessNum(n);
								TaskFileIndexInfo doc = taskServiceImpl.getIndexInfo((String) node.get("ID"));
								docs.add(doc);
							}
							// 1删除原索引，
							domain.setState(1);
							{
								DocIndexInter index = FarmLuceneFace.inctance()
										.getDocIndex(FarmLuceneFace.inctance().getIndexPathFile(LuceneIndexFileKey));
								try {
									List<String> ids = new ArrayList<>();
									for (TaskFileIndexInfo fileinfo : docs) {
										ids.add(fileinfo.getId());
									}
									index.deleteFhysicsIndex(ids, domain);
								} catch (Exception e) {
									log.error(e + e.getMessage(), e);
								} finally {
									try {
										if (index != null) {
											index.close();
										}
									} catch (Exception e) {
										throw new RuntimeException(e + "删除索引");
									}
								}
							}

							// 2添加新索引，
							domain.setState(2);
							{
								DocIndexInter index = FarmLuceneFace.inctance()
										.getDocIndex(FarmLuceneFace.inctance().getIndexPathFile(LuceneIndexFileKey));
								try {
									int addNum = 0;
									for (TaskFileIndexInfo fileinfo : docs) {
										try {
											domain.setProcessNum(domain.getCompletedNum() + (addNum++));
											// 创建分类索引
											index.indexDoc(fileinfo.getDocMap());
										} catch (Exception e) {
											throw new RuntimeException(e + "添加索引");
										}
									}
									// 为了下一次添加索引做准备，不然太慢了
									index.mergeIndex();
								} catch (Exception e) {
									throw new RuntimeException(e);
								} finally {
									try {
										if (index != null) {
											index.close();
										}
									} catch (Exception e1) {
										log.error("lucene error:" + e1);
									}
								}
							}
						} catch (SQLException e1) {
							e1.printStackTrace();
							break;
						}
					}
					// 3完成，
					domain.setState(3);
				} catch (Exception e) {
					domain.setState(-2);
					domain.setMessage(e.getMessage() + e);
				}
			}
		});
		t.start();
		return domain;
	}

	/**
	 * 获得索引任务状态
	 * 
	 * @param taskkey
	 * @return
	 */
	public static IndexTaskDomain getTaskState(String taskkey) {
		if (domains.get(taskkey) != null) {
			return domains.get(taskkey);
		} else {
			// 无此任务
			return new IndexTaskDomain(0, 0, -1, "-1无任务", taskkey);
		}
	}

	public static IRResult searchFiles(String name, final String exname, final String taskTypeId, Integer page,
			final Set<String> projectids) throws Exception {
		name = URLDecoder.decode(escapeQueryChars(name.replaceAll("%", "%25")), "utf-8");
		DocQueryInter query = FarmLuceneFace.inctance()
				.getDocQuery(FarmLuceneFace.inctance().getIndexPathFile(LuceneIndexFileKey));
		String iql = "WHERE(TEXT,FILENAME,TASKNAME,PROJECTNAME=" + name.trim() + ")-SLACK ";
		if (page == null) {
			page = 1;
		}
		IRResult result = query.queryByMultiIndex(iql, page, 10, new ScoreDocFilterInter() {
			@Override
			public boolean doScan(Document document) {
				if (!projectids.contains(document.get("PROJECTID"))) {
					return false;
				}
				// 處理後綴名
				if (StringUtils.isNotBlank(exname)) {
					String indexExName = document.get("EXNAME");
					String searchExName = exname;
					if (StringUtils.isBlank(indexExName)
							|| !searchExName.toUpperCase().equals(indexExName.toUpperCase())) {
						return false;
					}
				}
				// 处理任务类型
				if (StringUtils.isNotBlank(taskTypeId)) {
					if (!taskTypeId.equals(document.get("TASKTYPEID"))) {
						return false;
					}
				}

				return true;
			}
		});
		return result;
	}

	/**
	 * 删除全文检索中的特殊字符
	 * 
	 * @param word
	 * @return word
	 */
	public static String escapeQueryChars(String word) {
		word = word.trim();
		StringBuilder sb = new StringBuilder();
		String wipeChars = "\\+!():^[]&quot;{}~*?|&amp;;/='";
		wipeChars = wipeChars.replaceAll("&lt;", "<");
		wipeChars = wipeChars.replaceAll("&gt;", ">");
		wipeChars = wipeChars.replaceAll("&amp;", "&");
		wipeChars = wipeChars.replaceAll("&apos;", "'");
		wipeChars = wipeChars.replaceAll("&quot;", "\"");
		for (int i = 0; i < word.length(); i++) {
			char c = word.charAt(i);
			// These characters are part of the query syntax and must be escaped
			// if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' ||
			// c == ')' || c == ':' || c == '^'
			// || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c
			// == '~' || c == '*' || c == '?'
			// || c == '|' || c == '&' || c == ';' || c == '/' || c == '=') {
			if (wipeChars.trim().indexOf(String.valueOf(c)) >= 0) {
				sb.append("");
			} else {
				if (Character.isWhitespace(c)) {
					sb.append("+");
				} else {
					sb.append(c);
				}
			}
		}
		return sb.toString();
	}

	public static void deleteIndex(String fileid) {
		DocIndexInter index = null;
		try {
			index = FarmLuceneFace.inctance()
					.getDocIndex(FarmLuceneFace.inctance().getIndexPathFile(LuceneIndexFileKey));
			index.deleteFhysicsIndex(fileid);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (index != null) {
					index.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
